package org.pb.org.service.impl;

import org.assertj.core.util.CheckReturnValue;
import org.pb.basic.service.impl.BaseServiceImpl;
import org.pb.basic.utils.AjaxResult;
import org.pb.basic.utils.MD5Utils;
import org.pb.basic.utils.PageList;
import org.pb.basic.utils.StrUtils;
import org.pb.org.domain.Employee;
import org.pb.org.mapper.DepartmentMapper;
import org.pb.org.mapper.EmployeeMapper;
import org.pb.org.query.EmployeeQuery;
import org.pb.org.service.IEmployeeService;
import org.pb.user.domain.LoginInfo;
import org.pb.user.service.ILoginInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 员工对应的业务层实现类
 * @author
 */
@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class EmployeeServiceImpl extends BaseServiceImpl<Employee, EmployeeQuery> implements IEmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private ILoginInfoService loginInfoService;

    /**
     * 将员工类对象的数据映射到登录信息对象中的同名属性中
     * @param employee 员工实例
     * @return 返回得到映射值后的登陆信息对象
     */
    private LoginInfo Employee2LoginInfo(Employee employee) {
        LoginInfo loginInfo = new LoginInfo();
        // 通过工具工具类将员工对象和登录信息对象的同名属性进行映射
        BeanUtils.copyProperties(employee, loginInfo);
        return loginInfo;
    }

    @Override
    @Transactional
    public void save(Employee employee) {
        if (StringUtils.isEmpty(employee.getPassword())) {
            // 如果密码为空，则抛出异常，密码不能为空
            throw new RuntimeException("密码不能为空");
        }
        // 获取到了员工类的对象之后，对于员工类的密码进行加盐加密
        // 获取盐值
        String salt = StrUtils.getComplexRandomString(32);
        // 将密码和盐值进行拼接，然后通过MD5进行加密，获取到新的密码
        String newPassword = MD5Utils.encrypByMd5(employee.getPassword() + salt);
        // 将该密码设置为最终密码
        employee.setPassword(newPassword);
        // 添加员工数据，也要同步添加登陆信息表LoginInfo，执行employee转化为LoginInfo
        LoginInfo loginInfo = Employee2LoginInfo(employee);
        // 先添加登陆信息对应的数据
        loginInfoService.save(loginInfo);
        // 然后通过loginInfo参数获取到对应的LoginInfo的id
        employee.setLogininfo_id(loginInfo.getId());
        // 添加员工数据
        employeeMapper.save(employee);
    }

    @Override
    @Transactional
    public void update(Employee employee) {
        // 修改员工数据，也需要对密码进行重新的加盐加密
        String salt = StrUtils.getComplexRandomString(32);
        // 通过MD5获取到加密后的新密码
        String newPassword = MD5Utils.encrypByMd5(employee.getPassword() + salt);
        // 将employee中的盐值修改对应的盐值
        employee.setSalt(salt);
        // 将employee中的密码修改为新密码
        employee.setPassword(newPassword);
        // 将修改后的数据添加到loginInfo中
        LoginInfo loginInfo = Employee2LoginInfo(employee);
        // 将loginInfo参数中的id修改为Employee中的loginInfo_id的值
        loginInfo.setId(employee.getLogininfo_id());
        // 先修改loginInfo中的值
        loginInfoService.update(loginInfo);
        // 根据用户名和密码查询对应得到对应的loginInfo_id
        employeeMapper.update(employee);
    }

    @Override
    @Transactional
    public void remove(Long id) {
        // 删除员工数据前，还需要先删除对应部门中对应的经理id
        departmentMapper.updateByManager(id);
        // 根据员工的id获取到logininfo_id值
        Employee employee = employeeMapper.loadById(id);
        // 通过员工属性中的loginInfo的id删除对应的loginInfo
        loginInfoService.remove(employee.getLogininfo_id());
        // 删除了loginInfo的信息后，才能删除该员工数据
        employeeMapper.remove(id);
    }

    @Override
    public List<Employee> findAll() {
        return employeeMapper.findAll();
    }

    @Override
    public Employee getById(Long id) {
        if (id == null) {
            return null;
        }
        return employeeMapper.loadById(id);
    }

    @Override
    public PageList<Employee> findByQuery(EmployeeQuery query) {
        if (query == null) {
            throw new RuntimeException("查询条件不能为空");
        }
        // 获取到对应条件的记录条数
        Integer totals = employeeMapper.countQuery(query);
        // 如果总记录条数为0或者记录记录条数为空，则表示分页查询失败
        if (totals == null || totals <= 0) {
            throw new RuntimeException("查询失败");
        }
        // 获取对应的分页数据
        List<Employee> employees = employeeMapper.findByQuery(query);
        // 如果employees为空，则证明查询不到记录，则查询失败，直接返回一个空的集合
        if (employees == null) {
            return new PageList<>();
        }
        // 如果最后得到的分页数据不为空，则返回对应的记录条数和分页数据
        PageList<Employee> list = new PageList<>();
        list.setTotals(totals);
        list.setData(employees);
        return list;
    }

    @Override
    @Transactional
    public void batchRemove(List<Long> ids) {
        // 要批量删除员工数据的话，考虑该员工可能是一个部门经理，所以需要删除前先给部门manager_id为当前员工id的数据，进行修改，将manager_id置为空
        departmentMapper.batchUpdateByManaderId(ids);
        // 执行批量删除操作
        employeeMapper.batchRemove(ids);
    }

    @Override
    public AjaxResult isAdmin(Long id) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setId(id);
        // 通过loginInfo_id获取到employee信息
        Employee emp = employeeMapper.getByLogInfoId(loginInfo);
        // 判断是否有shop_id
        if (emp.getShop_id() != null) {
            return AjaxResult.successWithMessage("是管理员");
        } else {
            return AjaxResult.failedWithMessage("不是管理员");
        }
    }
}
